home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / image_render.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-08  |  17.3 KB  |  816 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include <gtk/gtk.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "gimprc.h"
  30. #include "gximage.h"
  31. #include "image_render.h"
  32. #include "pixel_region.h"
  33. #include "scale.h"
  34.  
  35. #include "tile.h"            /* ick. */
  36.  
  37. #include "libgimp/gimpmath.h"
  38.  
  39. typedef struct _RenderInfo  RenderInfo;
  40. typedef void (*RenderFunc) (RenderInfo *info);
  41.  
  42. struct _RenderInfo
  43. {
  44.   GDisplay *gdisp;
  45.   TileManager *src_tiles;
  46.   guint *alpha;
  47.   guchar *scale;
  48.   guchar *src;
  49.   guchar *dest;
  50.   int x, y;
  51.   int w, h;
  52.   float scalex;
  53.   float scaley;
  54.   int src_x, src_y;
  55.   int src_bpp;
  56.   int dest_bpp;
  57.   int dest_bpl;
  58.   int dest_width;
  59.   int byte_order;
  60. };
  61.  
  62.  
  63. /*  accelerate transparency of image scaling  */
  64. guchar *blend_dark_check = NULL;
  65. guchar *blend_light_check = NULL;
  66. guchar *tile_buf = NULL;
  67. guchar *check_buf = NULL;
  68. guchar *empty_buf = NULL;
  69. guchar *temp_buf = NULL;
  70.  
  71. static guint   check_mod;
  72. static guint   check_shift;
  73. static guint   tile_shift;
  74. static guchar  check_combos[6][2] =
  75. {
  76.   { 204, 255 },
  77.   { 102, 153 },
  78.   { 0, 51 },
  79.   { 255, 255 },
  80.   { 127, 127 },
  81.   { 0, 0 }
  82. };
  83.  
  84.  
  85.  
  86. void
  87. render_setup (int check_type,
  88.           int check_size)
  89. {
  90.   int i, j;
  91.  
  92.   /*  based on the tile size, determine the tile shift amount
  93.    *  (assume here that tile_height and tile_width are equal)
  94.    */
  95.   tile_shift = 0;
  96.   while ((1 << tile_shift) < TILE_WIDTH)
  97.     tile_shift++;
  98.  
  99.   /*  allocate a buffer for arranging information from a row of tiles  */
  100.   if (!tile_buf)
  101.     tile_buf = g_new (guchar, GXIMAGE_WIDTH * MAX_CHANNELS);
  102.  
  103.   if (check_type < 0 || check_type > 5)
  104.     g_error ("invalid check_type argument to render_setup: %d", check_type);
  105.   if (check_size < 0 || check_size > 2)
  106.     g_error ("invalid check_size argument to render_setup: %d", check_size);
  107.  
  108.   if (!blend_dark_check)
  109.     blend_dark_check = g_new (guchar, 65536);
  110.   if (!blend_light_check)
  111.     blend_light_check = g_new (guchar, 65536);
  112.  
  113.   for (i = 0; i < 256; i++)
  114.     for (j = 0; j < 256; j++)
  115.       {
  116.     blend_dark_check [(i << 8) + j] = (guchar)
  117.       ((j * i + check_combos[check_type][0] * (255 - i)) / 255);
  118.     blend_light_check [(i << 8) + j] = (guchar)
  119.       ((j * i + check_combos[check_type][1] * (255 - i)) / 255);
  120.       }
  121.  
  122.   switch (check_size)
  123.     {
  124.     case SMALL_CHECKS:
  125.       check_mod = 0x3;
  126.       check_shift = 2;
  127.       break;
  128.     case MEDIUM_CHECKS:
  129.       check_mod = 0x7;
  130.       check_shift = 3;
  131.       break;
  132.     case LARGE_CHECKS:
  133.       check_mod = 0xf;
  134.       check_shift = 4;
  135.       break;
  136.     }
  137.  
  138.   /*  calculate check buffer for previews  */
  139.   if (preview_size)
  140.     {
  141.       if (check_buf)
  142.     g_free (check_buf);
  143.       if (empty_buf)
  144.     g_free (empty_buf);
  145.       if (temp_buf)
  146.     g_free (temp_buf);
  147.  
  148.       check_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  149.       for (i = 0; i < (preview_size + 4); i++)
  150.     {
  151.       if (i & 0x4)
  152.         {
  153.           check_buf[i * 3 + 0] = blend_dark_check[0];
  154.           check_buf[i * 3 + 1] = blend_dark_check[0];
  155.           check_buf[i * 3 + 2] = blend_dark_check[0];
  156.         }
  157.       else
  158.         {
  159.           check_buf[i * 3 + 0] = blend_light_check[0];
  160.           check_buf[i * 3 + 1] = blend_light_check[0];
  161.           check_buf[i * 3 + 2] = blend_light_check[0];
  162.         }
  163.     }
  164.       empty_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  165.       memset (empty_buf, 0, (preview_size + 4) * 3);
  166.       temp_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  167.     }
  168.   else
  169.     {
  170.       check_buf = NULL;
  171.       empty_buf = NULL;
  172.       temp_buf = NULL;
  173.     }
  174. }
  175.  
  176. void
  177. render_free (void)
  178. {
  179.   g_free (tile_buf);
  180.   g_free (check_buf);
  181. }
  182.  
  183. /*  Render Image functions  */
  184.  
  185. static void    render_image_rgb       (RenderInfo *info);
  186. static void    render_image_rgb_a     (RenderInfo *info);
  187. static void    render_image_gray      (RenderInfo *info);
  188. static void    render_image_gray_a    (RenderInfo *info);
  189. static void    render_image_indexed   (RenderInfo *info);
  190. static void    render_image_indexed_a (RenderInfo *info);
  191.  
  192. static void    render_image_init_info          (RenderInfo   *info,
  193.                         GDisplay     *gdisp,
  194.                         int           x,
  195.                         int           y,
  196.                         int           w,
  197.                         int           h);
  198. static guint*  render_image_init_alpha         (int           mult);
  199. static guchar* render_image_accelerate_scaling (int           width,
  200.                         int           start,
  201.                         float         scalex);
  202. static guchar* render_image_tile_fault         (RenderInfo   *info);
  203.  
  204.  
  205. static RenderFunc render_funcs[6] =
  206. {
  207.     render_image_rgb,
  208.     render_image_rgb_a,
  209.     render_image_gray,
  210.     render_image_gray_a,
  211.     render_image_indexed,
  212.     render_image_indexed_a,
  213. };
  214.  
  215.  
  216. /*****************************************************************/
  217. /*  This function is the core of the display--it offsets and     */
  218. /*  scales the image according to the current parameters in the  */
  219. /*  gdisp object.  It handles color, grayscale, 8, 15, 16, 24,   */
  220. /*  & 32 bit output depths.                                      */
  221. /*****************************************************************/
  222.  
  223. void
  224. render_image (GDisplay *gdisp,
  225.           int       x,
  226.           int       y,
  227.           int       w,
  228.           int       h)
  229. {
  230.   RenderInfo info;
  231.   int image_type;
  232.  
  233.   render_image_init_info (&info, gdisp, x, y, w, h);
  234.  
  235.   image_type = gimage_projection_type (gdisp->gimage);
  236.   if ((image_type < 0) || (image_type > 5))
  237.     {
  238.       g_message ("unknown gimage projection type: %d",
  239.          gimage_projection_type (gdisp->gimage));
  240.       return;
  241.     }
  242.  
  243.   if ((info.dest_bpp < 1) || (info.dest_bpp > 4))
  244.     {
  245.       g_message ("unsupported destination bytes per pixel: %d", info.dest_bpp);
  246.       return;
  247.     }
  248.  
  249.   /* Currently, only RGBA and GRAYA projection types are used - the rest
  250.    * are in case of future need.  -- austin, 28th Nov 1998. */
  251.   if (image_type != RGBA_GIMAGE && image_type != GRAYA_GIMAGE)
  252.       g_warning ("using untested projection type %d", image_type);
  253.  
  254.   (* render_funcs[image_type]) (&info);
  255. }
  256.  
  257.  
  258.  
  259. /*************************/
  260. /*  8 Bit functions      */
  261. /*************************/
  262.  
  263. static void
  264. render_image_indexed (RenderInfo *info)
  265. {
  266.   guchar *src;
  267.   guchar *dest;
  268.   guchar *cmap;
  269.   gulong  val;
  270.   gint    byte_order;
  271.   gint    y, ye;
  272.   gint    x, xe;
  273.   gint    initial;
  274.  
  275.   cmap = gimage_cmap (info->gdisp->gimage);
  276.  
  277.   y = info->y;
  278.   ye = info->y + info->h;
  279.   xe = info->x + info->w;
  280.  
  281.   initial = TRUE;
  282.   byte_order = info->byte_order;
  283.   info->src = render_image_tile_fault (info);
  284.  
  285.   for (; y < ye; y++)
  286.     {
  287.       gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  288.  
  289.       if (!initial && (error == 0))
  290.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  291.       else
  292.     {
  293.       src = info->src;
  294.       dest = info->dest;
  295.  
  296.       g_return_if_fail (src != NULL);
  297.       
  298.       for (x = info->x; x < xe; x++)
  299.         {
  300.           val = src[INDEXED_PIX] * 3;
  301.           src += 1;
  302.  
  303.           dest[0] = cmap[val+0];
  304.           dest[1] = cmap[val+1];
  305.           dest[2] = cmap[val+2];
  306.           dest += 3;
  307.         }
  308.     }
  309.  
  310.       info->dest += info->dest_bpl;
  311.  
  312.       initial = FALSE;
  313.  
  314.       if (error >= 1)
  315.     {
  316.       info->src_y += error;
  317.       info->src = render_image_tile_fault (info);
  318.       initial = TRUE;
  319.     }
  320.     }
  321. }
  322.  
  323. static void
  324. render_image_indexed_a (RenderInfo *info)
  325. {
  326.   guchar *src;
  327.   guchar *dest;
  328.   guint  *alpha;
  329.   guchar *cmap;
  330.   gulong  r, g, b;
  331.   gulong  val;
  332.   guint   a;
  333.   gint    dark_light;
  334.   gint    byte_order;
  335.   gint    y, ye;
  336.   gint    x, xe;
  337.   gint    initial;
  338.  
  339.   cmap = gimage_cmap (info->gdisp->gimage);
  340.   alpha = info->alpha;
  341.  
  342.   y = info->y;
  343.   ye = info->y + info->h;
  344.   xe = info->x + info->w;
  345.  
  346.   initial = TRUE;
  347.   byte_order = info->byte_order;
  348.   info->src = render_image_tile_fault (info);
  349.  
  350.   for (; y < ye; y++)
  351.     {
  352.       gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  353.  
  354.       if (!initial && (error == 0) && (y & check_mod))
  355.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  356.       else
  357.     {
  358.       src = info->src;
  359.       dest = info->dest;
  360.  
  361.       dark_light = (y >> check_shift) + (info->x >> check_shift);
  362.  
  363.       g_return_if_fail (src != NULL);
  364.  
  365.       for (x = info->x; x < xe; x++)
  366.         {
  367.           a = alpha[src[ALPHA_I_PIX]];
  368.           val = src[INDEXED_PIX] * 3;
  369.           src += 2;
  370.  
  371.           if (dark_light & 0x1)
  372.         {
  373.           r = blend_dark_check[(a | cmap[val+0])];
  374.           g = blend_dark_check[(a | cmap[val+1])];
  375.           b = blend_dark_check[(a | cmap[val+2])];
  376.         }
  377.           else
  378.         {
  379.           r = blend_light_check[(a | cmap[val+0])];
  380.           g = blend_light_check[(a | cmap[val+1])];
  381.           b = blend_light_check[(a | cmap[val+2])];
  382.         }
  383.  
  384.         dest[0] = r;
  385.         dest[1] = g;
  386.         dest[2] = b;
  387.         dest += 3;
  388.  
  389.         if (((x + 1) & check_mod) == 0)
  390.           dark_light += 1;
  391.           }
  392.     }
  393.  
  394.       info->dest += info->dest_bpl;
  395.  
  396.       initial = FALSE;
  397.  
  398.       if (error >= 1)
  399.     {
  400.       info->src_y += error;
  401.       info->src = render_image_tile_fault (info);
  402.       initial = TRUE;
  403.     }
  404.     }
  405. }
  406.  
  407. static void
  408. render_image_gray (RenderInfo *info)
  409. {
  410.   guchar *src;
  411.   guchar *dest;
  412.   gulong  val;
  413.   gint    byte_order;
  414.   gint    y, ye;
  415.   gint    x, xe;
  416.   gint    initial;
  417.  
  418.   y = info->y;
  419.   ye = info->y + info->h;
  420.   xe = info->x + info->w;
  421.  
  422.   initial = TRUE;
  423.   byte_order = info->byte_order;
  424.   info->src = render_image_tile_fault (info);
  425.  
  426.   for (; y < ye; y++)
  427.     {
  428.       gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  429.  
  430.       if (!initial && (error == 0))
  431.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  432.       else
  433.     {
  434.       src = info->src;
  435.       dest = info->dest;
  436.       
  437.       g_return_if_fail (src != NULL);
  438.  
  439.       for (x = info->x; x < xe; x++)
  440.         {
  441.           val = src[GRAY_PIX];
  442.           src += 1;
  443.  
  444.           dest[0] = val;
  445.           dest[1] = val;
  446.           dest[2] = val;
  447.           dest += 3;
  448.         }
  449.     }
  450.  
  451.       info->dest += info->dest_bpl;
  452.  
  453.       initial = FALSE;
  454.  
  455.       if (error >= 1)
  456.     {
  457.       info->src_y += error;
  458.       info->src = render_image_tile_fault (info);
  459.       initial = TRUE;
  460.     }
  461.     }
  462. }
  463.  
  464. static void
  465. render_image_gray_a (RenderInfo *info)
  466. {
  467.   guchar *src;
  468.   guchar *dest;
  469.   guint  *alpha;
  470.   gulong  val;
  471.   guint   a;
  472.   gint    dark_light;
  473.   gint    byte_order;
  474.   gint    y, ye;
  475.   gint    x, xe;
  476.   gint    initial;
  477.  
  478.   alpha = info->alpha;
  479.  
  480.   y = info->y;
  481.   ye = info->y + info->h;
  482.   xe = info->x + info->w;
  483.  
  484.   initial = TRUE;
  485.   byte_order = info->byte_order;
  486.   info->src = render_image_tile_fault (info);
  487.  
  488.   for (; y < ye; y++)
  489.     {
  490.       gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  491.  
  492.       if (!initial && (error == 0) && (y & check_mod))
  493.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  494.       else
  495.     {
  496.       src = info->src;
  497.       dest = info->dest;
  498.  
  499.       dark_light = (y >> check_shift) + (info->x >> check_shift);
  500.  
  501.       g_return_if_fail (src != NULL);
  502.  
  503.       for (x = info->x; x < xe; x++)
  504.         {
  505.           a = alpha[src[ALPHA_G_PIX]];
  506.           if (dark_light & 0x1)
  507.         val = blend_dark_check[(a | src[GRAY_PIX])];
  508.           else
  509.         val = blend_light_check[(a | src[GRAY_PIX])];
  510.           src += 2;
  511.  
  512.           dest[0] = val;
  513.           dest[1] = val;
  514.           dest[2] = val;
  515.           dest += 3;
  516.  
  517.           if (((x + 1) & check_mod) == 0)
  518.         dark_light += 1;
  519.         }
  520.     }
  521.  
  522.       info->dest += info->dest_bpl;
  523.  
  524.       initial = FALSE;
  525.  
  526.       if (error >= 1)
  527.     {
  528.       info->src_y += error;
  529.       info->src = render_image_tile_fault (info);
  530.       initial = TRUE;
  531.     }
  532.     }
  533. }
  534.  
  535. static void
  536. render_image_rgb (RenderInfo *info)
  537. {
  538.   guchar *src;
  539.   guchar *dest;
  540.   gint    byte_order;
  541.   gint    y, ye;
  542.   gint    x, xe;
  543.   gint    initial;
  544.  
  545.   y = info->y;
  546.   ye = info->y + info->h;
  547.   xe = info->x + info->w;
  548.  
  549.   initial = TRUE;
  550.   byte_order = info->byte_order;
  551.   info->src = render_image_tile_fault (info);
  552.  
  553.   for (; y < ye; y++)
  554.     {
  555.       gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  556.  
  557.       if (!initial && (error == 0))
  558.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  559.       else
  560.     {
  561.       src = info->src;
  562.       dest = info->dest;
  563.  
  564.       g_return_if_fail (src != NULL);
  565.       
  566.       /* replace this with memcpy, or better yet, avoid it altogether? */
  567.       for (x = info->x; x < xe; x++)
  568.         {
  569.           dest[0] = src[0];
  570.           dest[1] = src[1];
  571.           dest[2] = src[2];
  572.  
  573.           src += 3;
  574.           dest += 3;
  575.         }
  576.     }
  577.  
  578.       info->dest += info->dest_bpl;
  579.  
  580.       initial = FALSE;
  581.  
  582.       if (error >= 1)
  583.     {
  584.       info->src_y += error;
  585.       info->src = render_image_tile_fault (info);
  586.       initial = TRUE;
  587.     }
  588.     }
  589. }
  590.  
  591.  
  592.  
  593. static void
  594. render_image_rgb_a (RenderInfo *info)
  595. {
  596.   guchar *src;
  597.   guchar *dest;
  598.   guint  *alpha;
  599.   gulong  r, g, b;
  600.   guint   a;
  601.   gint    dark_light;
  602.   gint    byte_order;
  603.   gint    y, ye;
  604.   gint    x, xe;
  605.   gint    initial;
  606.  
  607.   alpha = info->alpha;
  608.  
  609.   y = info->y;
  610.   ye = info->y + info->h;
  611.   xe = info->x + info->w;
  612.  
  613.   initial = TRUE;
  614.   byte_order = info->byte_order;
  615.   info->src = render_image_tile_fault (info);
  616.  
  617.   for (; y < ye; y++)
  618.     {
  619.       gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  620.       if (!initial && (error == 0) && (y & check_mod))
  621.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  622.       else
  623.     {
  624.       src = info->src;
  625.       dest = info->dest;
  626.  
  627.       dark_light = (y >> check_shift) + (info->x >> check_shift);
  628.  
  629.       g_return_if_fail (src != NULL);
  630.  
  631.       for (x = info->x; x < xe; x++)
  632.         {
  633.           a = alpha[src[ALPHA_PIX]];
  634.           if (dark_light & 0x1)
  635.         {
  636.           r = blend_dark_check[(a | src[RED_PIX])];
  637.           g = blend_dark_check[(a | src[GREEN_PIX])];
  638.           b = blend_dark_check[(a | src[BLUE_PIX])];
  639.         }
  640.           else
  641.         {
  642.           r = blend_light_check[(a | src[RED_PIX])];
  643.           g = blend_light_check[(a | src[GREEN_PIX])];
  644.           b = blend_light_check[(a | src[BLUE_PIX])];
  645.         }
  646.  
  647.           src += 4;
  648.  
  649.           dest[0] = r;
  650.           dest[1] = g;
  651.           dest[2] = b;
  652.           dest += 3;
  653.  
  654.           if (((x + 1) & check_mod) == 0)
  655.         dark_light += 1;
  656.         }
  657.     }
  658.  
  659.       info->dest += info->dest_bpl;
  660.  
  661.       initial = FALSE;
  662.  
  663.       if (error >= 1)
  664.     {
  665.       info->src_y += error;
  666.       info->src = render_image_tile_fault (info);
  667.       initial = TRUE;
  668.     }
  669.     }
  670. }
  671.  
  672. static void
  673. render_image_init_info (RenderInfo *info,
  674.             GDisplay   *gdisp,
  675.             int         x,
  676.             int         y,
  677.             int         w,
  678.             int         h)
  679. {
  680.   info->gdisp = gdisp;
  681.   info->src_tiles = gimage_projection (gdisp->gimage);
  682.   info->x = x + gdisp->offset_x;
  683.   info->y = y + gdisp->offset_y;
  684.   info->w = w;
  685.   info->h = h;
  686.   info->scalex = SCALEFACTOR_X (gdisp);
  687.   info->scaley = SCALEFACTOR_Y (gdisp);
  688.   info->src_x = UNSCALEX (gdisp, info->x);
  689.   info->src_y = UNSCALEY (gdisp, info->y);
  690.   info->src_bpp = gimage_projection_bytes (gdisp->gimage);
  691.   info->dest = gximage_get_data ();
  692.   info->dest_bpp = gximage_get_bpp ();
  693.   info->dest_bpl = gximage_get_bpl ();
  694.   info->dest_width = info->w * info->dest_bpp;
  695.   info->byte_order = gximage_get_byte_order ();
  696.   info->scale = render_image_accelerate_scaling (w, info->x, info->scalex);
  697.   info->alpha = NULL;
  698.  
  699.   switch (gimage_projection_type (gdisp->gimage))
  700.     {
  701.     case RGBA_GIMAGE:
  702.     case GRAYA_GIMAGE:
  703.     case INDEXEDA_GIMAGE:
  704.       info->alpha = render_image_init_alpha (gimage_projection_opacity (gdisp->gimage));
  705.       break;
  706.     default:
  707.       /* nothing special needs doing */
  708.       break;
  709.     }
  710. }
  711.  
  712. static guint*
  713. render_image_init_alpha (int mult)
  714. {
  715.   static guint *alpha_mult = NULL;
  716.   static int alpha_val = -1;
  717.   int i;
  718.  
  719.   if (alpha_val != mult)
  720.     {
  721.       if (!alpha_mult)
  722.     alpha_mult = g_new (guint, 256);
  723.  
  724.       alpha_val = mult;
  725.       for (i = 0; i < 256; i++)
  726.     alpha_mult[i] = ((mult * i) / 255) << 8;
  727.     }
  728.  
  729.   return alpha_mult;
  730. }
  731.  
  732. static guchar*
  733. render_image_accelerate_scaling (int   width,
  734.                  int   start,
  735.                  float scalex)
  736. {
  737.   static guchar *scale = NULL;
  738.   gint i;
  739.  
  740.   if (!scale)
  741.     scale = g_new (guchar, GXIMAGE_WIDTH + 1);
  742.  
  743.   for (i = 0; i <= width; i++)
  744.     {
  745.       scale[i] = floor ((start + 1) / scalex) - floor (start / scalex);
  746.       start++;
  747.     }
  748.  
  749.   return scale;
  750. }
  751.  
  752. static guchar*
  753. render_image_tile_fault (RenderInfo *info)
  754. {
  755.   Tile *tile;
  756.   guchar *data;
  757.   guchar *dest;
  758.   guchar *scale;
  759.   int width;
  760.   int tilex;
  761.   int tiley;
  762.   int srctilex, srctiley;
  763.   int step;
  764.   int bpp = info->src_bpp;
  765.   int x, b;
  766.  
  767.   tilex = info->src_x / TILE_WIDTH;
  768.   tiley = info->src_y / TILE_HEIGHT;
  769.  
  770.   tile = tile_manager_get_tile (info->src_tiles,
  771.                 srctilex=info->src_x, srctiley=info->src_y,
  772.                 TRUE, FALSE);
  773.   if (!tile)
  774.     return NULL;
  775.  
  776.   data = tile_data_pointer (tile, 
  777.                 info->src_x % TILE_WIDTH,
  778.                 info->src_y % TILE_HEIGHT);
  779.   scale = info->scale;
  780.   dest = tile_buf;
  781.  
  782.   x = info->src_x;
  783.   width = info->w;
  784.  
  785.   while (width--)
  786.     {
  787.       for (b = 0; b < bpp; b++)
  788.     *dest++ = data[b];
  789.  
  790.       step = *scale++;
  791.       if (step != 0)
  792.     {
  793.       x += step;
  794.       data += step * bpp;
  795.  
  796.       if ((x >> tile_shift) != tilex)
  797.         {
  798.           tile_release (tile, FALSE);
  799.           tilex += 1;
  800.  
  801.           tile = tile_manager_get_tile (info->src_tiles, srctilex=x,
  802.                         srctiley=info->src_y, TRUE, FALSE);
  803.           if (!tile)
  804.         return tile_buf;
  805.  
  806.           data = tile_data_pointer (tile, 
  807.                 x % TILE_WIDTH,
  808.                 info->src_y % TILE_HEIGHT);
  809.         }
  810.     }
  811.     }
  812.  
  813.   tile_release (tile, FALSE);
  814.   return tile_buf;
  815. }
  816.